﻿#include "SQLiteDB.h"
#include <iostream>

SQLiteDB::SQLiteDB(const std::string &filename) : db(nullptr) {
    // 初始化
}

bool SQLiteDB::open() {
    int rc = sqlite3_open("chat.db", &db);
    if (rc != SQLITE_OK) {
        std::cerr << "无法打开数据库: " << sqlite3_errmsg(db) << std::endl;
        return false;
    }
    // 创建表
    execute(R"(
        CREATE TABLE IF NOT EXISTS users (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            username TEXT UNIQUE NOT NULL,
            password TEXT NOT NULL,
            age INTEGER,
            email TEXT,
            created_at DATETIME DEFAULT CURRENT_TIMESTAMP
        );
    )");
    return true;
}

bool SQLiteDB::insertUser(const std::string &username,
                          const std::string &password, int age,
                          const std::string &email) {
    sqlite3_stmt *stmt;
    const char *sql = "INSERT INTO users (username, password, age, email) "
                      "VALUES (?, ?, ?, ?);";
    // 编译 SQL
    int rc = sqlite3_prepare_v2(db, sql, -1, &stmt, nullptr);
    if (rc != SQLITE_OK)
        return false;

    sqlite3_bind_text(stmt, 1, username.c_str(), -1, SQLITE_STATIC);
    sqlite3_bind_text(stmt, 2, password.c_str(), -1,
                      SQLITE_STATIC); // 实际应加密
    sqlite3_bind_int(stmt, 3, age);
    sqlite3_bind_text(stmt, 4, email.c_str(), -1, SQLITE_STATIC);

    // 执行预处理语句。
    // 返回值：
    // SQLITE_DONE：执行成功（对于 INSERT、UPDATE、DELETE）。
    // SQLITE_ROW：返回一行数据（对于 SELECT）。
    // 其他值：错误。
    rc = sqlite3_step(stmt);
    sqlite3_finalize(stmt);
    return rc == SQLITE_DONE;
}

bool SQLiteDB::checkUser(const std::string &username,
                         const std::string &password, int &userId) {
    sqlite3_stmt *stmt;
    const char *sql =
        "SELECT id FROM users WHERE username = ? AND password = ?;";
    int rc = sqlite3_prepare_v2(db, sql, -1, &stmt, nullptr);
    if (rc != SQLITE_OK)
        return false;

    sqlite3_bind_text(stmt, 1, username.c_str(), -1, SQLITE_STATIC);
    sqlite3_bind_text(stmt, 2, password.c_str(), -1, SQLITE_STATIC);

    bool found = false;
    // 如果返回 SQLITE_ROW，说明找到了匹配的行，从结果集中提取 id 并存入 userId
    if (sqlite3_step(stmt) == SQLITE_ROW) {
        userId = sqlite3_column_int(stmt, 0);
        found = true;
    }
    sqlite3_finalize(stmt); // 释放预编译语句的资源。
    return found;
}

//执行无返回结果的 SQL（如 CREATE, INSERT, UPDATE, DELETE）
bool SQLiteDB::execute(const std::string &sql) {
    char *errMsg = nullptr;
    int rc = sqlite3_exec(db, sql.c_str(), nullptr, nullptr, &errMsg);
    if (rc != SQLITE_OK) {
        std::cerr << "SQL 执行失败: " << errMsg << std::endl;
        sqlite3_free(errMsg); // 必须释放错误信息
        return false;
    }
    std::cout << "SQL 执行成功: " << sql.substr(0, 50)
              << (sql.size() > 50 ? "..." : "") << std::endl;
    return true;
}

//执行查询并回调处理每一行结果
bool SQLiteDB::query(
    const std::string &sql,
    const std::function<void(std::vector<std::string>)> &callback) {
    if (!callback) {
        std::cerr << "回调函数为空！" << std::endl;
        return false;
    }

    char *errMsg = nullptr;
    // 第3个参数：SQLite 每读取一行数据，就会调用这个 C 风格回调函数（Lambda
    // 表达式转换为函数指针）。
    // 第4个参数：用户数据（这里传入了 callback 的地址，用于在 C 回调中访问 C++
    // 的 std::function）。
    int rc = sqlite3_exec(
        db, sql.c_str(),
        //cb: 用户传入的上下文（即 &callback）。
        //argc：列数。 
        //argv：列值的数组（argv[i] 是第 i 列的值，可能是 NULL）。
        //colName：列名数组（本例未使用）
        [](void *cb, int argc, char **argv, char **colName) -> int {
            std::function<void(std::vector<std::string>)> *callbackFunc =
                static_cast<std::function<void(std::vector<std::string>)> *>(
                    cb);

            std::vector<std::string> row;
            for (int i = 0; i < argc; ++i) {
                row.push_back(argv[i] ? argv[i] : "NULL");
            }

            (*callbackFunc)(row); // 调用用户传入的回调
            return 0;             // 继续处理下一行
        },
        const_cast<void *>(static_cast<const void *>(&callback)), &errMsg);

    if (rc != SQLITE_OK) {
        std::cerr << "查询失败: " << errMsg << std::endl;
        sqlite3_free(errMsg);
        return false;
    }

    return true;
}

SQLiteDB::~SQLiteDB() {
    if (db)
        sqlite3_close(db);
}